<script setup lang='ts'>
import {watch, ref, onBeforeUnmount, reactive, onMounted, effect, nextTick, CSSProperties} from 'vue'
import { ElScrollbar } from 'element-plus'
import { IconConfig, SeleteData } from '@/api/config'
import {routerPush, RouterPushType} from '@/util/router'
import {useRoute} from 'vue-router'
import {WelcomeView} from '@/store/nav'
import {HOMENAME} from '@/router/static'
import emitter from '@/util/mitt'

import tabBubble from './tabBubble.vue'
import useNav from '@/store/nav'
import dIcon from '@/components/dIcon.vue'
const nav = useNav.setup().store

const tabScrollbarRef = ref<InstanceType<typeof ElScrollbar>>()
const tabsWapperRef = ref<HTMLDivElement>()

const closeIcon:IconConfig = {icon:'Close', type:'el', size:15}
const historyIcon:IconConfig = {icon:'head-history', type:'custom', size:13}
const leftIcon:IconConfig = {icon:'head-left', type:'custom', size:10}
const rightIcon:IconConfig = {icon:'head-right', type:'custom', size:10}
const activeBoxStyle = reactive({
  width: '0',
  transform: 'translateX(0px)'
})


const showMove = ref(false)
const scrollbarMargin = 20
const tabsScrollbarStyle = () => {
  const style:CSSProperties = {}
  if (showMove.value) {
    style.marginLeft = scrollbarMargin + 'px'
    style.marginRight = scrollbarMargin + 'px'
  }
  return style
}

const selectNavTab = (code:string) => {
  nextTick(() => {
    if (!code || !tabsWapperRef.value) return
    const index = nav.getNavTabIndex(code)
    if (index === -1) return
    const tabDom = tabsWapperRef.value.children[index] as HTMLDivElement
    if (!tabDom) return
    activeBoxStyle.width = tabDom.clientWidth + 'px'
    activeBoxStyle.transform = `translateX(${tabDom.offsetLeft}px)`
    const tabScrollbar = tabScrollbarRef.value
    if (!tabScrollbar) return
    const tabScrollbarEl:HTMLDivElement = tabScrollbar.$el
    const tabScrollbarView = tabScrollbarEl.childNodes[0] as HTMLDivElement
    if (!tabScrollbarView) return
    const add = tabScrollbarView.scrollWidth > tabScrollbarView.clientWidth && showMove.value === false
    const addNum = add ? scrollbarMargin : 0
    const scrollLeft = tabDom.offsetLeft + tabDom.clientWidth - tabScrollbarView.clientWidth
    if (tabDom.offsetLeft < tabScrollbarView.scrollLeft) {
      tabScrollbar.setScrollLeft(tabDom.offsetLeft + addNum)
    } else if (scrollLeft > tabScrollbarView.scrollLeft) {
      tabScrollbar.setScrollLeft(scrollLeft + addNum)
    }
    showMove.value = tabScrollbarView.scrollWidth > tabScrollbarView.clientWidth
  })
}

//移动
const onMove = (toLeft:boolean) => {
  const tabScrollbar = tabScrollbarRef.value
  if (!tabScrollbar) return
  const tabScrollbarEl:HTMLDivElement = tabScrollbar.$el
  const tabScrollbarView = tabScrollbarEl.children[0] as HTMLDivElement
  const step = tabScrollbarView.scrollWidth
  let left = tabScrollbarView.scrollLeft
  if (toLeft) left -= step
  else left += step
  tabScrollbar.setScrollLeft(left)
}

const getTabTitle = (code:string) => {
  if (!nav.navMenuHash) return ''
  const menu = nav.navMenuHash[code]
  return menu ? menu.label : ''
}

const history = ref<Array<SeleteData>>([])
const updateHistory = (code:string|null) => {
  if (!code) return
  //更新下拉
  const arr:Array<SeleteData> = []
  arr.push({value:code, label: getTabTitle(code)})
  for (let i = 0, l = history.value.length; i < l; i++) {
    const item = history.value[i]
    if (item.value !== code) {
      arr.push({value:item.value, label:getTabTitle(item.value as string)})
    }
  }
  history.value = arr
}

effect(() => {
  if (nav.navTabSelete) selectNavTab(nav.navTabSelete)
  updateHistory(nav.navTabSelete)
})

const route = useRoute()
watch(
  () => route.name,
  () => {
    if (route.name !== nav.navTabSelete && nav.getNavTabByCode(route.name as string)) {
      routerPush(route.name as string, undefined, RouterPushType.Others)
    } else if (route.name === HOMENAME) {
      routerPush(WelcomeView.code, undefined, RouterPushType.Others)
    }
  }
)


const onTab = (code:string|null) => {
  if (!code || !nav.navTabSelete) return
  const currentMenu = nav.getNavTabByCode(code)
  routerPush(currentMenu, undefined, RouterPushType.Tab)
  if (code === nav.navTabSelete) {
    selectNavTab(nav.navTabSelete)
  }
}

const closeTab = (code:string) => {
  nav.closeTab(code)
  onTab(nav.navTabSelete)
}

const onLeft = () => {
  nav.backTab()
  onTab(nav.navTabSelete)
}
const onRight = () => {
  nav.forwardTab()
  onTab(nav.navTabSelete)
}

const onCommand = (code:string) => {
  onTab(code)
}

const hoverTab = ref('')
const onMouseenter = (code:string) => {
  hoverTab.value = code
}
const onMouseleave = (code:string) => {
  if (hoverTab.value === code) hoverTab.value = ''
}
const getIconShow = (code:string) => {
  if (code === WelcomeView.code) return false
  return nav.navTabSelete === code || hoverTab.value === code
}

const bubbleX = ref(0)
const bubbleY = ref(0)
const showBubble = ref(false)

const onClick = () => {
  showBubble.value = false
}

watch(showBubble, (showBubble) => {
  if (showBubble) {
    document.addEventListener('click', onClick)
  } else {
    document.removeEventListener('click', onClick)
  }
})

const rightMenu = ref('')
const onContextmenu = (code:string, evt:MouseEvent) => {
  showBubble.value = true
  rightMenu.value = code
  bubbleX.value = evt.clientX
  bubbleY.value = evt.clientY
}

const onCloseOthers = () => {
  showBubble.value = false
  nav.setNavSeleteTab(rightMenu.value)
  nav.closeOtherTab()
}


const onReload = () => {
  showBubble.value = false
  const currentMenu = nav.getNavTabByCode(rightMenu.value)
  if (!currentMenu) return
  emitter.emit('viewRefresh', currentMenu)
}

onMounted(() => {
  if (nav.navTabSelete) selectNavTab(nav.navTabSelete)
})
onBeforeUnmount(() => {
  showBubble.value = false
  hoverTab.value = ''
})
</script>

<template>
  <div class="home-tabs-conent --home-tabs-height d-common-flex-row">
    <el-scrollbar ref="tabScrollbarRef" class="home-tabs-scrollbar d-hide-elscrollbar d-common-flex-full" :style="tabsScrollbarStyle()" wrap-class="d-common-post-rel d-common-flex-row">
      <div ref="tabsWapperRef" class="home-tabs-wapper">
        <div
          v-for="item in nav.navTabOpenArr"
          :key="item"
          class="home-tabs-item"
          :class="nav.navTabSelete===item?'active':''"
          @click="onTab(item)"
          @mouseenter="onMouseenter(item)"
          @mouseleave="onMouseleave(item)"
          @contextmenu.prevent="onContextmenu(item,$event)"
        >
          <span>{{ getTabTitle(item) }}</span>
          <d-icon v-if="getIconShow(item)" :icon-config="closeIcon" class="close-icon" @click.stop="closeTab(item)" />
        </div>
        <div :style="activeBoxStyle" class="home-tabs-active-box" />
      </div>
    </el-scrollbar>
    <div class="home-tabs-btns d-common-flex-row d-common-flex-algin-center">
      <el-dropdown :show-timeout="100" :hide-timeout="100" @command="onCommand">
        <div class="home-tabs-btnbox d-common-flex-center">
          <d-icon :icon-config="historyIcon" />
        </div>
        <template #dropdown>
          <el-dropdown-menu v-if="history.length>0">
            <el-dropdown-item v-for="item in history" :key="''+item.value" :command="''+item.value">
              {{ item.label }}
            </el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
      <div class="home-tabs-btnbox d-common-flex-center" @click="onLeft">
        <d-icon :icon-config="leftIcon" />
      </div>
      <div class="home-tabs-btnbox d-common-flex-center" @click="onRight">
        <d-icon :icon-config="rightIcon" />
      </div>
    </div>
  </div>
  <tab-bubble v-if="showBubble" :client-x="bubbleX" :client-y="bubbleY" @close-others="onCloseOthers" @reload="onReload" />
</template>

<style scoped lang="less">
.home-tabs-conent{
  position: relative;
  padding: 5px 15px 0px 15px;
  --home-tabs-height:48px;
  height: var(--home-tabs-height);
}
.home-tabs-scrollbar{
  height: var(--home-tabs-height);
  background-color: var(--d-color-white);
}
.home-tabs-wapper{
  height: calc(var(--home-tabs-height) - 5px);
  display: flex;
  position: relative;
}
.home-tabs-item{
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  cursor: pointer;
  z-index: 1;
  white-space: nowrap;
  height: 100%;
  color: var(--d-font-color-tab);
  transition: all 0.2s;
  -webkit-transition: all 0.2s;
  position: relative;
  min-width: 80px;
  border-radius: var(--d-border-radius-level-2) var(--d-border-radius-level-2) 0 0;
  box-sizing: border-box;
  .close-icon {
    margin-left: 6px;
  }
  .close-icon:hover {
    background-color: var(--theme-color) !important;
    border-radius: 50%;
  }
  &.active {
    color: var(--d-icon-color-grey);
    background-color: var(--d-color-grey-2);
    border-top: 3px solid var(--theme-color);
  }
  &:hover {
    // background-color: black;
  }
}
.home-tabs-active-box {
  position: absolute;
  height: calc(var(--home-tabs-height) - 5px);
  background-color: var();
  transition: all 0.2s;
  -webkit-transition: all 0.2s;
}
.home-tabs-move{
  position: absolute;
  cursor: pointer;
  height: calc(var(--home-tabs-height) - 5px);
  padding-top: 15px;
  width: 20px;
  color: var(--d-color-white);
  z-index: 2;
}
.home-tabs-prev{
  left: 0;
  top: 0;
}
.home-tabs-next{
  right: 0;
  top: 0;
}
.home-tabs-btns{
  height: 100%;
  padding: 4px 0 9px 0;
  column-gap: 4px;
  .home-tabs-btnbox{
    height: 30px;
    width: 34px;
    background: var(--d-color-white);
    border-radius: var(--d-border-radius-level-2);
    opacity: 1;
    border: 1px solid var(--d-icon-color-border);
    &:hover{
      background: var(--d-color-grey-3);
      border: 1px solid var(--d-font-color-assist-1);
      cursor: pointer;
    }
  }
}
</style>